package com.mycat.tencent.server;

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.mycat.exception.PaymentException;
import com.mycat.tencent.config.ConfigInfo;
import com.mycat.tencent.entity.request.HttpRequestParams;
import com.mycat.tencent.entity.request.WxAppRefundParams;
import com.mycat.tencent.entity.request.WxAppRefundQueryParams;
import com.mycat.tencent.entity.response.HttpResponseParam;
import com.mycat.tencent.entity.response.WxRefundQueryResponse;
import com.mycat.tencent.entity.response.WxRefundResponse;
import com.mycat.tencent.http.WxHttp;
import com.mycat.tencent.util.Sign;
import com.mycat.tencent.util.Utils;
import com.mycat.util.parser.api.Parser;
import com.mycat.util.parser.xml.XmlParser;

/**
 * @desc 微信退款服务
 * @author roger
 * @date 2016年9月26日
 */
@SuppressWarnings("deprecation")
public class WxRefundService {

    private static Parser parser;

    static {
        parser = new XmlParser();
    }

    /**
     * 微信App支付后申请退款
     *
     * @param refundParams WxAppRefundParams
     * @param payWay 微信支付方式
     * @return WxRefundResponse
     */
    public static WxRefundResponse applyRefund(WxAppRefundParams refundParams) throws Exception {
        if (null == refundParams) {
            throw new PaymentException("请求参数错误");
        }
        try {
            refundParams.setAppid(ConfigInfo.appid);
            refundParams.setMch_id(ConfigInfo.mch_id);
            refundParams.setNonce_str(Utils.createSonceStr());
            refundParams.setOp_user_id(ConfigInfo.mch_id);
            // 转换为Map
            Map<String, Object> params = refundParams.toMap();
            // 获取签名
            String sign = Sign.createSign(params, ConfigInfo.sing_key);
            params.put("sign", sign);
            // 拼装请求参数为XML
            String requestParam = Utils.toXmlStr(params);
            // 进行请求
            String content = doRefund(requestParam);

            WxRefundResponse response = parser.from(content, WxRefundResponse.class);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            throw new PaymentException("SDK出现异常");
        }
    }

    /**
     * 退款查询服务
     * @param refundNo 退款订单号
     * @return  WxRefundQueryResponse
     * @throws Exception
     */
    public static WxRefundQueryResponse refundQuery(String refundNo) throws Exception {
        try {
            WxAppRefundQueryParams queryParams = new WxAppRefundQueryParams();
            queryParams.setAppid(ConfigInfo.appid);
            queryParams.setMch_id(ConfigInfo.mch_id);
            queryParams.setNonce_str(Utils.createSonceStr());
            queryParams.setOut_refund_no(refundNo);

            // 转换为Map
            Map<String, Object> params = queryParams.toMap();
            // 获取签名
            String sign = Sign.createSign(params, ConfigInfo.sing_key);
            params.put("sign", sign);
            // 拼装请求参数为XML
            String requestParam = Utils.toXmlStr(params);
            // 进行Http请求退款
            HttpRequestParams httpRequestParams = new HttpRequestParams();
            httpRequestParams.setUri(ConfigInfo.refund_query_url);
            httpRequestParams.setRequestParams(requestParam);
            // 进行请求
            HttpResponseParam httpResponseParam = WxHttp.getInstance().post(httpRequestParams);

            WxRefundQueryResponse response = parser.from(httpResponseParam.getContent(), WxRefundQueryResponse.class);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            throw new PaymentException("SDK出现异常");
        }
    }


    public File getCertFile(){
    	return new File(getClass().getResource("/apiclient_cert.p12").getPath());
    }
    
    /**
     * 发起微信退款
     * @param data 退款参数XML格式字符串
     * @return 响应结果Content
     * @throws Exception
     */
    private static String doRefund(String data) throws Exception {
        /**
         * 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
         */

        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        FileInputStream instream = null;
        try {
        	instream = new FileInputStream(new File(ClassLoader.class.getResource("/apiclient_cert.p12").getPath()));//P12文件目录
		} catch (Exception e) {
			throw new PaymentException("获取微信证书失败");
		}
        try {
            /**
             * 此处要改
             */
            keyStore.load(instream, ConfigInfo.mch_id.toCharArray());//这里写密码..默认是你的MCHID
        } finally {
            instream.close();
        }

        /**
         * 此处要改
         */
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, ConfigInfo.mch_id.toCharArray())//这里也是写密码的
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[]{"TLSv1"},
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        try {
            HttpPost httpost = new HttpPost(ConfigInfo.refund_url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();

                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }

}
